﻿#include <algorithm>
#include <string.h>
#include "bufferedstream.h"

BufferedInputStream::BufferedInputStream(InputStream * next, int buffersize):InputStream(next)
{
	this->buffersize = buffersize;
}

int BufferedInputStream::doRead(unsigned char * buffer, int readLen) throw(StreamException)
{
	CheckBuffer(readLen);

	int ret = std::min(readLen, (int)m_buffer.size());
	
    memcpy((char*)buffer, &*m_buffer.begin(), ret);

	m_buffer.erase(m_buffer.begin(), m_buffer.begin() + ret);

	return ret;
}

int BufferedInputStream::avaliable() const
{
	return this->m_buffer.size() + GetNext()->avaliable();
}

void BufferedInputStream::CheckBuffer(int readLen)
{
	if (m_buffer.size() < readLen) {
		FillBuffer(readLen);
	}
}

void BufferedInputStream::FillBuffer(int readLen)
{
	auto next = GetNext();
	if (!next) {
		return;
	}
	int bufferRead = std::min(buffersize,GetNext()->avaliable());//缓存策略不会去读取超出预期的部分
	int realReadLen = std::max(readLen, buffersize);
	unsigned char * temp = new unsigned char[realReadLen];
	next->read(temp, realReadLen);
	delete[]temp;
	m_buffer.insert(m_buffer.end(), temp, temp + realReadLen);
}

BufferedOutputStream::BufferedOutputStream(OutputStream * next, int buffersize):OutputStream(next)
{
	this->buffersize = buffersize;
}

void BufferedOutputStream::write(const unsigned char * buffer, int len) throw(StreamException)
{
	m_buffer.insert(m_buffer.end(), buffer, buffer + len);
	CheckBuffer();
}

void BufferedOutputStream::flush()
{
	FlushBuffer();
	GetNext()->flush();
}

void BufferedOutputStream::CheckBuffer()
{
	if (buffersize > m_buffer.size()) {
		FlushBuffer();
	}
}

void BufferedOutputStream::FlushBuffer()
{
	auto next = GetNext();
	if (next) {
		next->write(&*m_buffer.begin(), m_buffer.size());
		m_buffer.clear();
	}
}
